﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Yunlib.Common
{
    public class Interceptor
    {
        #region 单例
        private static Interceptor _instance;
        private static readonly Object syncLock = new Object();
        /// <summary>  
        /// 单例模式  
        /// </summary>  
        public static Interceptor Instance
        {
            get
            {
                if (Interceptor._instance == null)
                {
                    lock (syncLock)
                    {
                        if (Interceptor._instance == null)
                        {
                            Interceptor._instance = new Interceptor();
                        }
                    }
                }
                return Interceptor._instance;
            }
        }

        #endregion
        static List<IInterceptor> interceptors { get; set; }

        int index = -1;

        /// <summary>
        /// 返回值方法
        /// </summary>
        Action aMethod { get; set; }

        /// <summary>
        /// 方法名
        /// </summary>
        public string MethodName { get; set; }

        /// <summary>
        /// 类名
        /// </summary>
        public string ClassName { get; set; }


        [DebuggerStepThrough]
        public Interceptor()
        {
            if (interceptors == null)
            {
                interceptors = new List<IInterceptor>();
                //interceptors.Add(new ExceptionLogger());
                interceptors.Add(new TimeConsumingLogger());
                interceptors.Add(new ConsoleLogger());
            }
        }

        /// <summary>
        /// 注册方法
        /// </summary>
        /// <param name="method"></param>
        [DebuggerStepThrough]
        public Interceptor Register(Action method, bool ValidateToken = true)
        {
            StackTrace st = new StackTrace();
            this.MethodName = st.GetFrame(1).GetMethod().Name;
            this.ClassName = st.GetFrame(1).GetMethod().ReflectedType.Name;

            index = -1;
            aMethod = method;
            return this;
        }


        /// <summary>
        /// 调用
        /// </summary>
        [DebuggerStepThrough]
        public void Invoke()
        {
            if (++index >= interceptors.Count)
            {
                if (aMethod != null) aMethod();
            }
            else
            {
                interceptors[index].Intercept(this);
            }
        }
    }

    public class Interceptor<T>
    {
        #region 单例
        private static Interceptor<T> _instance;
        private static readonly Object syncLock = new Object();
        /// <summary>  
        /// 单例模式  
        /// </summary>  
        public static Interceptor<T> Instance
        {
            get
            {
                if (Interceptor<T>._instance == null)
                {
                    lock (syncLock)
                    {
                        if (Interceptor<T>._instance == null)
                        {
                            Interceptor<T>._instance = new Interceptor<T>();
                        }
                    }
                }
                return Interceptor<T>._instance;
            }
        }

        #endregion

        static List<IInterceptor> interceptors { get; set; }

        int index = -1;

        /// <summary>
        /// 返回值方法
        /// </summary>
        Func<T> fMethod { get; set; }

        /// <summary>
        /// 方法名
        /// </summary>
        public string MethodName { get; set; }

        /// <summary>
        /// 类名
        /// </summary>
        public string ClassName { get; set; }


        [DebuggerStepThrough]
        public Interceptor()
        {
            if (interceptors == null)
            {
                interceptors = new List<IInterceptor>();
                //interceptors.Add(new ExceptionLogger());
                interceptors.Add(new TimeConsumingLogger());
                interceptors.Add(new ConsoleLogger());
            }
        }

        /// <summary>
        /// 注册方法
        /// </summary>
        /// <param name="method"></param>
        [DebuggerStepThrough]
        public Interceptor<T> Register(Func<T> method, bool ValidateToken = true)
        {
            StackTrace st = new StackTrace();
            this.MethodName = st.GetFrame(1).GetMethod().Name;
            this.ClassName = st.GetFrame(1).GetMethod().ReflectedType.Name;
            index = -1;
            fMethod = method;
            return this;
        }


        /// <summary>
        /// 调用
        /// </summary>
        [DebuggerStepThrough]
        public T Invoke()
        {
            if (++index >= interceptors.Count)
            {
                if (fMethod != null) return fMethod();

                return default(T);
            }
            else
            {
                return interceptors[index].Intercept(this);
            }
        }
    }


    public interface IInterceptor
    {
        [DebuggerStepThrough]
        T Intercept<T>(Interceptor<T> actionInvocation);

        [DebuggerStepThrough]
        void Intercept(Interceptor actionInvocation);
    }

    public class ConsoleLogger : IInterceptor
    {
        [DebuggerStepThrough]
        public T Intercept<T>(Interceptor<T> actionInvocation)
        {
            PerformanceTest.Instance.Start("{0}.{1}".FormatWith(actionInvocation.ClassName, actionInvocation.MethodName));
            T result = actionInvocation.Invoke();
            PerformanceTest.Instance.End("{0}.{1}".FormatWith(actionInvocation.ClassName, actionInvocation.MethodName));
            return result;
        }

        [DebuggerStepThrough]
        public void Intercept(Interceptor actionInvocation)
        {
            PerformanceTest.Instance.Start("{0}.{1}".FormatWith(actionInvocation.ClassName, actionInvocation.MethodName));
            actionInvocation.Invoke();
            PerformanceTest.Instance.End("{0}.{1}".FormatWith(actionInvocation.ClassName, actionInvocation.MethodName));
        }
    }

    public class TimeConsumingLogger : IInterceptor
    {
        [DebuggerStepThrough]
        public T Intercept<T>(Interceptor<T> actionInvocation)
        {
            Stopwatch myWatch = Stopwatch.StartNew();
            T result = actionInvocation.Invoke();
            myWatch.Stop();
            LoggerHelper.Info("方法名:{0}\t".FormatWith(actionInvocation.MethodName) + "类名:{0}\t".FormatWith(actionInvocation.ClassName) + "使用时间:{0}\r\n".FormatWith("一共耗时{0}ms".FormatWith(myWatch.ElapsedMilliseconds.ToString("N0"))));
            return result;
        }

        [DebuggerStepThrough]
        public void Intercept(Interceptor actionInvocation)
        {
            Stopwatch myWatch = Stopwatch.StartNew();
            actionInvocation.Invoke();
            myWatch.Stop();
            LoggerHelper.Info("方法名:{0}\t".FormatWith(actionInvocation.MethodName) + "类名:{0}\t".FormatWith(actionInvocation.ClassName) + "使用时间:{0}\r\n".FormatWith("一共耗时{0}ms".FormatWith(myWatch.ElapsedMilliseconds.ToString("N0"))));
        }
    }

    public class ExceptionLogger : IInterceptor
    {
        //[DebuggerStepThrough]
        public T Intercept<T>(Interceptor<T> actionInvocation)
        {
            try
            {
                return actionInvocation.Invoke();
            }
            catch (Exception ex)
            {
                LoggerHelper.Error("方法名:{0}\t".FormatWith(actionInvocation.MethodName) + "类名:{0}\t".FormatWith(actionInvocation.ClassName) + "\r异常信息:" + ex.Message + "\r异常描述:{0}".FormatWith(ex.StackTrace));
            }
            return default(T);
        }

        //[DebuggerStepThrough]
        public void Intercept(Interceptor actionInvocation)
        {
            try
            {
                actionInvocation.Invoke();
            }
            catch (Exception ex)
            {
                LoggerHelper.Error("方法名:{0}\t".FormatWith(actionInvocation.MethodName) + "类名:{0}\t".FormatWith(actionInvocation.ClassName) + "\r异常信息:" + ex.Message + "\r异常描述:{0}".FormatWith(ex.StackTrace));
            }
        }
    }
}
